package yxy.game.pm2.module.arena;

import org.joda.time.DateTime;
import yxy.apple.util.concurrent.ThreadPoolManager;
import yxy.cherry.battle.Team;
import yxy.cherry.battle.module.record.result.BattleResult;
import yxy.cherry.data.DataCenter;
import yxy.cherry.data.bean.arenadate;
import yxy.cherry.data.script.fomula;
import yxy.cherry.data.string.GameString;
import yxy.game.pm2.Result;
import yxy.game.pm2.bean.Format.FormatType;
import yxy.game.pm2.bean.PlayerBean;
import yxy.game.pm2.bean.module.rank.RankEntry;
import yxy.game.pm2.bean.module.rank.openserviceactive.OpenServiceRushRankEnum;
import yxy.game.pm2.bean.module.rank.openserviceactive.arenarushrank.OpenServiceArenaRushRank;
import yxy.game.pm2.bean.task.TaskType;
import yxy.game.pm2.message.ArenaMessage;
import yxy.game.pm2.message.BattleMessage;
import yxy.game.pm2.message.PlayerMessage;
import yxy.game.pm2.module.NotificationHandle;
import yxy.game.pm2.module.active.openservicerush.OpenServiceRushRecord;
import yxy.game.pm2.module.battle.*;
import yxy.game.pm2.module.player.PlayerHandle;
import yxy.game.pm2.module.player.RankPlayerPower;
import yxy.game.pm2.module.stat.StatHandle;
import yxy.game.pm2.module.task.TaskHandle;
import yxy.game.pm2.module.tip.TipHandle;
import yxy.game.pm2.module.tip.TipType;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;

/**
 * 竞技场
 */
public class ArenaHandle {

    private String code() {
        return BattleType.ARENA.name();
    }

    public Result battleResponseExecute(ArenaPlayerModule module, String oppoCode, ArenaMessage.ArenaChanllengeStartResponse.Builder response) throws Exception {
        String playerCode = module.getPlayerCode();
        BattleHandle battleHandle = new BattleHandle();

        BattleModule battleModule = BattleModule.create(playerCode);
        battleModule.setType(BattleType.ARENA);
        battleModule.setCode(code());

        // 玩家的team
        TeamModule teamA = battleHandle.teamPlayer(playerCode, FormatType.普通);
        battleModule.setTeamA(teamA);

        // 玩家的team
        TeamModule teamB = battleHandle.teamPlayer(oppoCode, FormatType.普通);
        battleModule.setTeamB(teamB);

        //todo 修改登录时间，3天后自动清除缓存
        StatHandle.stat_用户登录状态更新(oppoCode);

        Team team_a = teamA.team(true);
        Team team_b = teamB.team(false);
        team_a.setTeam对手(team_b);
        team_b.setTeam对手(team_a);

        // 处理战斗
        battleHandle.battleExecute(battleModule, team_a, team_b, 20);
        boolean isWin = battleModule.getBattleResult().equals(BattleResult.LEFT_WIN);

        // 处理分数和奖励
        RankArena rankArena = RankArena.getRank(playerCode);

        RankEntry rankEntryA = rankArena.get(playerCode);
        if (rankEntryA == null) {
            rankArena.put(playerCode, fomula.竞技场初始分数.intValue());
            rankEntryA = rankArena.get(playerCode);
        }
        RankEntry rankEntryB = rankArena.get(oppoCode);

        ArenaPlayerModule arenaModuleA = module;
        ArenaPlayerModule arenaModuleB = ArenaPlayerModule.get(oppoCode);

        int oriScoreA = rankEntryA.getValue().intValue();
        int oriScoreB = rankEntryB == null ? fomula.竞技场初始分数.intValue() : rankEntryB.getValue().intValue();
        int finScoreA = oriScoreA;
        int finScoreB = oriScoreB;

        int scoreChangeA = 0;
        int scoreChangeB = 0;

        {
            int deduct = 0;
            // 进攻方
            if (arenaModuleA != null) {
                arenadate data = data(oriScoreA);
                if (isWin) {
                    int score = fomula.竞技场积分计算公式.intValue(Double.valueOf(data.getRankapex()), Double.valueOf(oriScoreA), Double.valueOf(oriScoreB),
                            0);
                    int add = score * data.getIncrease() / 10000;
                    finScoreA = oriScoreA + add;
                    int combo = arenaModuleA.getCombo() + 1;
                    arenaModuleA.setCombo(combo);
                    if (combo == 3 || combo >= 5) {
                        // 滚屏消息
                        PlayerBean playerBean = PlayerBean.get(playerCode);
                        new NotificationHandle().notifyChatInner(playerCode, GameString.再擂台中取得N连胜(playerBean.getName(), combo));
                    }
                    deduct = score * data.getDeduction() / 10000;
                } else {
                    arenaModuleA.setCombo(0);
                    finScoreA = oriScoreA + data.getChallengedefeat();
                }
                arenaModuleA.setTimes(arenaModuleA.getTimes() + 1);
                arenaModuleA.setWeektimes(arenaModuleA.getWeektimes() + 1);
                arenaModuleA.set();
                scoreChangeA = finScoreA - oriScoreA;

                rankArena.put(playerCode, finScoreA);
            }
            // 防守方
            {
                finScoreB = finScoreB - deduct;
                scoreChangeB = finScoreB - oriScoreB;
                if (rankEntryB != null) {
                    rankArena.put(oppoCode, finScoreB);
                }
            }
        }

        // 处理录像
        {
            BattleRecord battleRecord = battleModule.saveRecord(BattleRecord.randomCode(), 1);
            ArenaRecord arenaRecord = new ArenaRecord();
            arenaRecord.setAttackerCode(playerCode);
            arenaRecord.setDefenderCode(oppoCode);
            arenaRecord.setDate(DateTime.now());
            arenaRecord.setBattleResult(battleModule.getBattleResult());
            arenaRecord.setRecordCode(battleRecord.getCode());
            arenaRecord.setScoreChangeAttacker(scoreChangeA);
            arenaRecord.setScoreChangeDefender(scoreChangeB);
            if (arenaModuleA != null) {
                ArenaRecord.add(playerCode, arenaRecord);
            }
            if (arenaModuleB != null) {
                ArenaRecord.add(oppoCode, arenaRecord);
            }

            new TipHandle().updateTip(oppoCode, TipType.主城_竞技场建筑, true);// 挨打了要有红点提示
        }

        // 封装消息
        {
            ArenaMessage.ArenaFighter.Builder fighterA = packFighter(playerCode);
            if (arenaModuleA != null) {
                fighterA.setScore(finScoreA);
                fighterA.setChange(scoreChangeA);
            }

            ArenaMessage.ArenaFighter.Builder fighterB = packFighter(oppoCode);
            if (rankEntryB != null) {
                fighterB.setScore(finScoreB);
                fighterB.setChange(scoreChangeB);
            } else {
                fighterB.setScore(oriScoreB);
                fighterB.setChange(0);
            }

            BattleMessage.BattleExecuteResponse.Builder builder = BattleMessage.BattleExecuteResponse.newBuilder();
            builder.setPlayback(battleHandle.playback(battleModule));// , team_a, team_b));

            response.setBattleResp(builder);// 录像
            response.setBattleResult(battleModule.getBattleResult().getNumber());// 战果

            response.setFighterA(fighterA);// 进攻方
            response.setFighterB(fighterB);// 防守方
        }

        // 刷新对手
        refreshOppo(module);
        {
            //兼容武将
            {
                int finalFinScoreA = finScoreA;
                Runnable runnableA = () -> TaskHandle.handle(playerCode, TaskType.指标型_擂台_积分_达到, finalFinScoreA);
                Runnable runnableB = () -> TaskHandle.handle(playerCode, TaskType.统计型_擂台_次数, 1);
                ThreadPoolManager.getInstance().execute(runnableA);
                ThreadPoolManager.getInstance().execute(runnableB);
                Runnable runnableC = () -> {
                    int differScore = OpenServiceArenaRushRank.updateArenaRanking(
                            playerCode,
                            finalFinScoreA,
                            OpenServiceRushRankEnum.开服冲榜_竞技争雄.getType());
                    if(differScore > 0){
                        OpenServiceRushRecord.recordFirstCompleteAreanTask(playerCode,differScore);
                    }
                };
                ThreadPoolManager.getInstance().execute(runnableC);
            }
        }

        return Result.Success;
    }

    public ArenaMessage.ArenaFighter.Builder packFighter(String playerCode) {
        ArenaMessage.ArenaFighter.Builder builder = ArenaMessage.ArenaFighter.newBuilder();
        PlayerBean player = PlayerBean.get(playerCode);
        builder.setPlayerCode(player.getCode());
        builder.setNickname(player.getName());
        builder.setHead(player.getHead());
        builder.setHeadFrame(player.getHeadframe());
        builder.setLevel(player.getLevel());
        return builder;
    }

    public Result record(String playerCode, ArenaMessage.ArenaChanllengeRecordResponse.Builder response) {
        List<ArenaRecord> list = ArenaRecord.get(playerCode);
        for (ArenaRecord record : list) {
            boolean isAttacker = record.getAttackerCode().equals(playerCode);

            ArenaMessage.ArenaRecord.Builder builder = ArenaMessage.ArenaRecord.newBuilder();
            builder.setAttack(isAttacker);
            builder.setRecord(record.getRecordCode());
            builder.setDate(record.getDate().getMillis());
            builder.setOppoInfo(oppoInfo(//
                    isAttacker ? record.getDefenderCode() : record.getAttackerCode()));
            builder.setResult(record.getBattleResult().getNumber());
            builder.setScore(isAttacker ? record.getScoreChangeAttacker() : record.getScoreChangeDefender());

            response.addRecords(builder);
        }

        return Result.Success;
    }

    public Collection<ArenaMessage.RankArena> refreshOppo(ArenaPlayerModule module) {
        randomOppo(module);
        return getOppo(module);
    }

    public Collection<ArenaMessage.RankArena> getOppo(String playerCode) {
        ArenaPlayerModule module = ArenaPlayerModule.get(playerCode);
        if (module == null) {
            return new ArrayList<>();
        }
        if (module.getOppo() == null || module.getOppo().size() <= 0) {
            randomOppo(module);
        }
        return getOppo(module);
    }

    private Collection<ArenaMessage.RankArena> getOppo(ArenaPlayerModule module) {
        RankArena rankArena = RankArena.getRank(module.getPlayerCode());
        int initScore = fomula.竞技场初始分数.intValue();
        ArrayList<ArenaMessage.RankArena> list = new ArrayList<>();
        for (String pcode : module.getOppo()) {
            RankEntry rankEntry = rankArena.get(pcode);
            int score = initScore;
            if (rankEntry != null) {
                score = rankEntry.getValue().intValue();
            }
            ArenaMessage.RankArena.Builder builder = ArenaMessage.RankArena.newBuilder();
            builder.setScore(score);
            builder.setPlayerInfo(oppoInfo(pcode));
            builder.setRank(0);
            list.add(builder.build());
        }
        return list;
    }

    private void randomOppo(ArenaPlayerModule module) {
        String playerCode = module.getPlayerCode();
        int size = 5;// 对手数量
        ArrayList<String> oppoList = new ArrayList<>();
        Collection<RankEntry> randomOppo = RankArena.getRank(playerCode).randomList(playerCode, 4, 4, size);
        if (randomOppo.size() < size) {
            randomOppo = RankPlayerPower.getRank(playerCode).randomEntry(playerCode, 100, 100, size);// 竞技场排名不够用的话 去战力排行榜里找
        }
        for (RankEntry entry : randomOppo) {
            oppoList.add(entry.getKey());
        }
        module.setOppo(oppoList);
        module.set();
    }

    public PlayerMessage.PlayerSimpleInfo.Builder oppoInfo(String playerCode) {
        return new PlayerHandle().playerSimpleInfo(playerCode);
    }

    public arenadate data(int score) {
        Map<String, arenadate> all = DataCenter.getAllData(arenadate.class);
        arenadate worsedata = null;
        for (arenadate data : all.values()) {
            if (worsedata == null) {
                worsedata = data;
            }
            if (data.getIntegralmin() > score) {
                continue;
            }
            if (data.getIntegralmax() < 0 || data.getIntegralmax() <= score) {
                return data;
            }
        }
        return worsedata;
    }
}
